#include "../StdAfx.h"
#include "Folder.h"
#include "EnumIDList.h"

using namespace SevenZip;

IFACEMETHODIMP CSevenZipEnumIDList::Next(ULONG Count, PITEMID_CHILD * Result, ULONG * Fetched)
{
	if (Count == 0)
	{
		return S_OK;
	}

	if (Result != NULL)
	{
		if ((Count > 1) && (Fetched == NULL))
		{
			return E_INVALIDARG;
		}

		HRESULT hr = S_OK;

		if (!_Started)
		{
			hr = StartEnumeration();
		}

		if (SUCCEEDED(hr))
		{
			ULONG f = 0;

			for (; SUCCEEDED(hr) && (f < Count) && (_Position < _ItemIndices.GetCount()); _Position++)
			{
				if (SUCCEEDED(hr = _Owner->_CreateItemID(_ItemIndices.GetAt(_Position), &Result[f])))
				{
					f++;
				}
			}

			if (SUCCEEDED(hr))
			{
				hr = (Count == f) ? S_OK : S_FALSE;
				*Fetched = f;
			}
			else
			{
				while (f > 0)
				{
					f--;
					::CoTaskMemFree(Result[f]);
				}
				
			}
		}

		return hr;
	}

	return E_POINTER;
}

IFACEMETHODIMP CSevenZipEnumIDList::Skip(ULONG Elements)
{
	_Position += Elements;
	return S_OK;
}

IFACEMETHODIMP CSevenZipEnumIDList::Reset()
{
	_Position = 0;
	return S_OK;
}

IFACEMETHODIMP CSevenZipEnumIDList::Clone(IEnumIDList ** Clone)
{
	HRESULT hr = E_POINTER;

	if (Clone != NULL)
	{
		CComPtr<CSevenZipEnumIDList> Object;

		if (SUCCEEDED(hr = CoCreate(Object)))
		{
			if (SUCCEEDED(hr = Object->Initialize(_Owner, _Folder, _Flags)))
			{
				Object->_Position = _Position;
				*Clone = Object.Detach();
			}
		}
	}

	return hr;
}

STDMETHODIMP CSevenZipEnumIDList::Initialize(CComPtrEx<CSevenZipFolder> & Owner, CSevenZipArchiveItem * Folder, SHCONTF Flags)
{
	_Owner = Owner;
	_Flags = Flags;
	_Folder = Folder;
	_Started = FALSE;
	_Position = 0;

	if (!(Flags & SHCONTF_INIT_ON_FIRST_NEXT))
	{
		return StartEnumeration();
	}

	return S_OK;
}

STDMETHODIMP CSevenZipEnumIDList::StartEnumeration()
{
	_Started = TRUE;

	HRESULT hr = S_OK;
	size_t Count = _Folder->GetItemCount();

	for (size_t i = 0; SUCCEEDED(hr) && (i < Count); i++)
	{
		BOOL IsFolder;
		CSevenZipArchiveItem * Item = _Folder->GetItem(i);

		if (SUCCEEDED(hr = Item->IsFolder(&IsFolder)))
		{
			if (( IsFolder && (_Flags & SHCONTF_FOLDERS)) ||
				(!IsFolder && (_Flags & SHCONTF_NONFOLDERS)))
			{
				_ItemIndices.Add(i);
			}
		}
	}

	return hr;
}